{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import io\n",
    "import platform\n",
    "import sklearn\n",
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split\n",
    "import sklearn.datasets as datasets\n",
    "import random\n",
    "import pandas as pd\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torch.utils.data as data\n",
    "from torch.utils.data.dataset import Dataset\n",
    "import torch.nn.functional as F\n",
    "from torch.autograd import Variable\n",
    "\n",
    "import torchvision\n",
    "import torchvision.datasets as datasets\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "from PIL import Image\n",
    "from PIL import ImageOps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class CNN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN,self).__init__()\n",
    "        self.cl1=nn.Conv2d(3,12,kernel_size=5,padding=2) # tunable here\n",
    "        self.mp1=nn.MaxPool2d(2)\n",
    "        self.cl2=nn.Conv2d(12,3,kernel_size=5,padding=2)\n",
    "        self.mp2=nn.MaxPool2d(2)\n",
    "        self.fcl=nn.Linear(7500,200) # 12 x 27 x 27\n",
    "        \n",
    "    def forward(self,x):\n",
    "        # x dim: b x 800 x 600 x 3 -> b x 1 x 100 x 100\n",
    "        out=F.relu(self.cl1(x))\n",
    "        out=self.mp1(out)\n",
    "        out=F.relu(self.cl2(out))\n",
    "        out=self.mp2(out)\n",
    "        \n",
    "        # tensor size of b x inchannels x 1 x 1\n",
    "        out=out.view(out.size(0),-1)\n",
    "        out=F.sigmoid(self.fcl(out))\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ContrastiveLoss(torch.nn.Module):\n",
    "    \"\"\"\n",
    "    Contrastive loss function.\n",
    "    Based on: http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, margin=2.0):\n",
    "        super(ContrastiveLoss, self).__init__()\n",
    "        self.margin = margin\n",
    "\n",
    "    def forward(self, output1, output2):\n",
    "        euclidean_distance = F.pairwise_distance(output1, output2)\n",
    "        loss_contrastive = torch.mean(torch.pow(euclidean_distance, 2) +\n",
    "                                      torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))\n",
    "\n",
    "#         loss_contrastive=torch.mean(torch.pow(euclidean_distance,2))\n",
    "        return loss_contrastive"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_model(path,model):\n",
    "    model.load_state_dict(torch.load(path))\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CNN(\n",
       "  (cl1): Conv2d(3, 12, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))\n",
       "  (mp1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (cl2): Conv2d(12, 3, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))\n",
       "  (mp2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (fcl): Linear(in_features=7500, out_features=200, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cnn=CNN()\n",
    "load_model('./model.pt',cnn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CNN(\n",
       "  (cl1): Conv2d(3, 12, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))\n",
       "  (mp1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (cl2): Conv2d(12, 3, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))\n",
       "  (mp2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (fcl): Linear(in_features=7500, out_features=200, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "img1=transforms.ToTensor()(Image.open('./LAG/stas_mikhailov/Aprile_01891_1.png').convert('RGB'))\n",
    "img2=transforms.ToTensor()(Image.open('./LAG/stas_mikhailov/y/Aprile_01891_2.png').convert('RGB'))\n",
    "p1=model(img1.unsqueeze(0))\n",
    "p2=model(img2.unsqueeze(0))\n",
    "loss=criterion(p1,p2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
